package engine.core
{
	import flash.events.*;
	import flash.utils.*;
	
	public class RxTimerWorker
	{
		protected var m_timer:Timer;
		protected var m_running:Boolean;
		protected var m_timeSlice:Number;
		protected var m_tasksRead:Vector.<Vector.<WorkerTask>>;
		protected var m_tasksWrite:Vector.<Vector.<WorkerTask>>;
		protected var m_numTasksQueued:uint;
		protected var m_totalTime:Number;
		protected var m_asynchronous:Boolean;
		public static const PRIORITY_LOWEST:uint = 0;
		public static const PRIORITY_LOW:uint = 1;
		public static const PRIORITY_NORMAL:uint = 2;
		public static const PRIORITY_HIGH:uint = 3;
		public static const PRIORITY_HIGHEST:uint = 4;
		public static const NUM_PRIORITIES:uint = 5;
		private static const s_maxIoTasks:int = 2;
		
		public function RxTimerWorker(delay:Number, timeSlice:Number)
		{
			this.m_timer = new Timer(1000 / delay, 0);
			this.m_timer.addEventListener(TimerEvent.TIMER, this.OnTimerEvent);
			this.m_running = true;
			this.m_timeSlice = timeSlice;
			this.m_tasksRead = new Vector.<Vector.<WorkerTask>>(NUM_PRIORITIES, true);
			this.m_tasksWrite = new Vector.<Vector.<WorkerTask>>(NUM_PRIORITIES, true);
			var i:int = 0;
			while (i < NUM_PRIORITIES)
			{
				
				this.m_tasksRead[i] = new Vector.<WorkerTask>;
				this.m_tasksWrite[i] = new Vector.<WorkerTask>;
				i++;
			}
			
			this.m_numTasksQueued = 0;
			this.m_totalTime = 0;
			this.m_asynchronous = true;
		}
		
		protected function OnTimerEvent(e:TimerEvent) : void
		{
			var task:Vector.<WorkerTask> = null;
			var len:int = 0;
			var workerTask:WorkerTask = null;
			var callback:RxCallback = null;
			var isIoTask:Boolean = false;
			var popTask:WorkerTask = null;
			var curTime:int = getTimer();
			var dis:uint = 0;
			var offset:Number = 0;
			var j:uint = 0;
			var bol:Boolean = false;
			var curCount:int = 0;
			
			var i:uint = PRIORITY_HIGHEST;
			while (i >= PRIORITY_LOWEST)
			{
				
				if (this.m_tasksWrite[i].length > 0)
				{
					this.m_tasksRead[i] = this.m_tasksRead[i].concat(this.m_tasksWrite[i]);
					this.m_tasksWrite[i].length = 0;
				}
				
				task = this.m_tasksRead[i];
				len = task.length - 1;
				while (len >= 0)
				{
					
					workerTask = task[len];
					callback = workerTask.m_callback;
					isIoTask = workerTask.m_isIoTask;
					if (isIoTask)
					{
						if (curCount >= s_maxIoTasks)
						{
						}
						curCount++;
					}
					
					if (callback.m_function(callback))
					{
						popTask = task.pop();
						if (workerTask != popTask)
						{
							task[len] = popTask;
							len++;
						}
						
						this.m_numTasksQueued = this.m_numTasksQueued - 1;
					}
					
					dis = getTimer() - curTime;
					j = j + 1;
					offset = Number(dis) / Number(j);
					if (dis + offset > this.m_timeSlice)
					{
						bol = true;
						break;
					}
					
					len = len - 1;
				}
				
				if (bol)
				{
					break;
				}
				
				i = i - 1;
			}
			
			if (this.m_numTasksQueued == 0)
			{
				this.m_timer.stop();
			}
			
			this.m_totalTime = this.m_totalTime + (getTimer() - curTime);
		}
		
		public function AddTask(param1:uint, param2:RxCallback, param3:Boolean = false) : void
		{
			var _loc_4:WorkerTask = null;
			if (param2 != null)
			{
				if (!this.m_asynchronous)
				{
					param2.m_function(param2);
		
				}
				_loc_4 = new WorkerTask();
				_loc_4.m_callback = param2;
				_loc_4.m_isIoTask = param3;
				this.m_tasksWrite[param1].push(_loc_4);
				this.m_numTasksQueued = this.m_numTasksQueued + 1;
				if (this.m_running && !this.m_timer.running)
				{
					this.m_timer.start();
				}
			}
		}
		
		public function RemoveTask(param1:RxCallback, param2:Boolean) : uint
		{
			var _loc_4:int = 0;
			var _loc_3:uint = 0;
			_loc_4 = 0;
			while (_loc_4 < NUM_PRIORITIES)
			{
				
				_loc_3 = _loc_3 + this.RemoveTaskFromArray(this.m_tasksWrite[_loc_4], param1, param2);
				if (param2 && _loc_3 > 0)
				{
					break;
				}
				_loc_4++;
			}
			return _loc_3;
		}
		
		private function RemoveTaskFromArray(param1:Vector.<WorkerTask>, param2:RxCallback, param3:Boolean) : uint
		{
			var _loc_5:int = 0;
			var _loc_4:uint = 0;
			_loc_5 = 0;
			while (_loc_5 < param1.length)
			{
				
				if (param1[_loc_5].m_callback == param2)
				{
					if (param1.length > 1)
					{
						param1[_loc_5] = param1[(param1.length - 1)];
						_loc_5 = _loc_5 - 1;
					}
					param1.pop();
					_loc_4 = _loc_4 + 1;
					this.m_numTasksQueued = this.m_numTasksQueued - 1;
					if (param3)
					{
						break;
					}
				}
				_loc_5++;
			}
			return _loc_4;
		}
		
		public function SetAsynchronous(param1:Boolean) : void
		{
			this.m_asynchronous = param1;
		}
		
		public function GetTotalTicks() : uint
		{
			return this.m_timer.currentCount;
		}
		
		public function GetTotalTime() : Number
		{
			return this.m_totalTime;
		}
		
		public function Adjust(param1:Number, param2:Number) : void
		{
			this.m_timer.delay = param1;
			this.m_timeSlice = param2;

		}
		
		public function Start() : void
		{
			this.m_running = true;
			if (this.m_numTasksQueued > 0 && !this.m_timer.running)
			{
				this.m_timer.start();
			}

		}
		
		public function Stop() : void
		{
			this.m_running = false;
			if (this.m_timer.running)
			{
				this.m_timer.stop();
			}

		}
		
		public function Delete() : void
		{
			var _loc_1:int = 0;
			if (this.m_timer.running)
			{
				this.m_timer.stop();
			}
			this.m_timer.removeEventListener(TimerEvent.TIMER, this.OnTimerEvent);
			this.m_timer = null;
			_loc_1 = 0;
			while (_loc_1 < NUM_PRIORITIES)
			{
				
				this.m_tasksRead[_loc_1] = null;
				this.m_tasksWrite[_loc_1] = null;
				_loc_1++;
			}
			this.m_tasksRead = null;
			this.m_tasksWrite = null;
			this.m_numTasksQueued = 0;

		}
		
		public function CountTaskByType(param1:Class) : uint
		{
			var _loc_3:int = 0;
			var _loc_4:int = 0;
			var _loc_5:Vector.<WorkerTask> = null;
			var _loc_2:uint = 0;
			_loc_3 = 0;
			while (_loc_3 < NUM_PRIORITIES)
			{
				
				_loc_5 = this.m_tasksWrite[_loc_3];
				_loc_4 = 0;
				while (_loc_4 < _loc_5.length)
				{
					
					if (_loc_5[_loc_4].m_callback is param1)
					{
						_loc_2 = _loc_2 + 1;
					}
					_loc_4++;
				}
				_loc_5 = this.m_tasksRead[_loc_3];
				_loc_4 = 0;
				while (_loc_4 < _loc_5.length)
				{
					
					if (_loc_5[_loc_4].m_callback is param1)
					{
						_loc_2 = _loc_2 + 1;
					}
					_loc_4++;
				}
				_loc_3++;
			}
			return _loc_2;
		}
		
		public function ClearTasks() : void
		{
			var _loc_1:int = 0;
			_loc_1 = 0;
			while (_loc_1 < NUM_PRIORITIES)
			{
				
				this.m_tasksRead[_loc_1].length = 0;
				this.m_tasksWrite[_loc_1].length = 0;
				_loc_1++;
			}
			this.m_numTasksQueued = 0;
			if (this.m_timer.running)
			{
				this.m_timer.stop();
			}
		}
		
		public function FinishTasks() : void
		{
			var _loc_1:* = this.m_timeSlice;
			this.m_timeSlice = Number.MAX_VALUE;
			this.OnTimerEvent(null);
			this.m_timeSlice = _loc_1;
		}
		
		public function IsAsynchronous() : Boolean
		{
			return this.m_asynchronous;
		}
	}
}

import engine.core.*;
class WorkerTask extends Object
{
	public var m_callback:RxCallback;
	public var m_isIoTask:Boolean;
	
	function WorkerTask()
	{
	}
}